import tensorflow as tf


def label_type_to_id(type_name, bin_class=False):
    flaw_type_names = ['正常', '扎洞', '毛斑', '擦洞', '毛洞', '织稀', '吊经', '缺经', '跳花', '油／污渍', '其他']
    if bin_class:
        return 0 if type_name == '正常' else 1

    if type_name == "油渍" or type_name == "污渍":
        type_name = '油／污渍'
    try:
        return flaw_type_names.index(type_name)
    except ValueError:
        return flaw_type_names.index('其他')


def typeid2defect_code(typeid):
    """
    传入瑕疵编号，返回defect_code，为最后结果统计服务
    0 --> norm
    1 --> defect_1
    2 --> defect_2
    ...s
    :param typeid:  整型
    :return: 字符串
    """
    return 'norm' if typeid == 0 else 'defect_{}'.format(typeid)


def parse_csv_to_dic(csv_path):
    """
    将csv文件解析为dic
    dic = {image_name1:[],image_name2:[],image_name3:[],...}
    其中[]为 [瑕疵个数,Xmin,Ymin,Xmax,Ymax,瑕疵名，Xmin,Ymin,Xmax,Ymax,瑕疵名...]
    :param csv_path:string
    :return:dic
    """
    dic = {}
    # 获取一张图片
    with open(csv_path, encoding='UTF-8') as f:
        lines = [line.strip().split(',') for line in f.readlines()]
    for line in lines:
        dic[line[0]] = line[1:-1]

    # print(dic)
    return dic


def calc_iou(rect1, rect2):
    """
    计算两矩形重叠面积
    :param rect1: (xmin1, ymin1, xmax1, ymax1)
    :param rect2: (xmin2, ymin2, xmax2, ymax2)
    :return: int 重叠面积
    """
    xmin1, ymin1, xmax1, ymax1 = rect1
    xmin2, ymin2, xmax2, ymax2 = rect2
    xmin = max(xmin1, xmin2)
    ymin = max(ymin1, ymin2)
    xmax = min(xmax1, xmax2)
    ymax = min(ymax1, ymax2)
    width = xmax - xmin
    height = ymax - ymin
    if width <= 0 or height <= 0:
        return 0
    cross_square = width * height
    return cross_square


def calc_confusion_metrics(predict_list, true_list):
    """
    根据传入的两个list，计算accuracy,precision,recall
    :return:accuracy,precision,recall
    """
    TP = 0
    FP = 0
    FN = 0
    TN = 0
    n = len(predict_list)
    for i in range(n):
        if predict_list[i] == true_list[i] and true_list[i] != 0:
            TP += 1
        elif predict_list[i] == true_list[i] and true_list[i] == 0:
            TN += 1
        elif predict_list[i] != true_list[i] and true_list[i] != 0:
            FN += 1
        else:
            FP += 1
    accuracy = (TP + TN) / n
    # 捕获潜在的除零错误
    precision = TP / float(TP + FP)
    recall = TP / float(TP + FN)
    return accuracy, precision, recall


def tf_confusion_metrics(predictions, actuals):
    """
    根据传入的两个list_op，计算accuracy_op,precision_op,recall_op
    :param predictions:预测的结果op
    :param actuals:真实标签op
    :return:accuracy_op,precision_op,recall_op
    """
    ones_like_actuals = tf.ones_like(actuals)
    zeros_like_actuals = tf.zeros_like(actuals)
    ones_like_predictions = tf.ones_like(predictions)
    zeros_like_predictions = tf.zeros_like(predictions)

    tp_op = tf.reduce_sum(
        tf.cast(
            tf.logical_and(
                tf.equal(actuals, ones_like_actuals),
                tf.equal(predictions, ones_like_predictions)
            ),
            "float"
        )
    )

    tn_op = tf.reduce_sum(
        tf.cast(
            tf.logical_and(
                tf.equal(actuals, zeros_like_actuals),
                tf.equal(predictions, zeros_like_predictions)
            ),
            "float"
        )
    )

    fp_op = tf.reduce_sum(
        tf.cast(
            tf.logical_and(
                tf.equal(actuals, zeros_like_actuals),
                tf.equal(predictions, ones_like_predictions)
            ),
            "float"
        )
    )

    fn_op = tf.reduce_sum(
        tf.cast(
            tf.logical_and(
                tf.equal(actuals, ones_like_actuals),
                tf.equal(predictions, zeros_like_predictions)
            ),
            "float"
        )
    )

    accuracy = (tp_op + tn_op) / (tp_op + fp_op + fn_op + tn_op)
    # 捕获潜在的除零错误
    precision = tp_op / float(tp_op + fp_op)
    recall = tp_op / float(tp_op + fn_op)
    f1_score = (2 * (precision * recall)) / float(precision + recall)
    return accuracy, precision, recall, f1_score
